#pragma once
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "common.hpp"
#include "log.hpp"
#include"Intaddr.hpp"

using namespace LogModule;

const static uint16_t gdefaultport = 8080;
const static int gsockfd = -1;




class UdpServer
{
public:
    UdpServer(uint16_t port = gdefaultport)
        : _netaddr(port),
          _sockfd(gsockfd),
          _isrunning(false)
    {
    }

    void InitServer()
    {
        //1.创建socket文件
        _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0); //没有Int  这里如果定义了一个变量  _sockfd的值就是没有变化的
        if (_sockfd < 0)                            //加 int 会变成局部变量，导致成员变量未被修改。
        {
            LOG(LogLevel::FATAL) << "socket: " << strerror(errno);
            Die(SOCKET_ERR);
        }
        LOG(LogLevel::INFO) << "socket success, sockfd is : " << _sockfd;

        //2.填充网络信息并bind
        // struct sockaddr_in local;
        // bzero(&local, sizeof(local));//先置零
        // local.sin_family = AF_INET;  
        // local.sin_port = ::htons(_port); // 要被发送给对方的，即要发到网络中！
        // // local.sin_addr.s_addr = ::inet_addr(_ip.c_str()); // 服务器ip不用绑定 1. string ip->4bytes 2. network order //TODO
        // local.sin_addr.s_addr = INADDR_ANY;
        
        //bind
        int n = ::bind(_sockfd , _netaddr.NetAddr() , _netaddr.NetAddrLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind: " << strerror(errno);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind success";
        
    }

    void Start()
    {
        _isrunning=true;
        //服务器启动一直运行
        while(true)
        {
            //缓冲区和输出型参数
            char inbuffer[1024]; // string
            struct sockaddr_in client;
            socklen_t len = sizeof(client); 

            //服务器收信息
            ssize_t n = ::recvfrom(_sockfd ,inbuffer ,sizeof(inbuffer)-1 ,0 ,CONV(&client) , &len);
            if (n > 0)
            {
                std::cout<<"我已收到"<<std::endl;
                // 1. 消息内容 && 2. 谁发给我的
                //16位网络数据 → 主机字节序(大端/小端)
                // uint16_t clientport = ::ntohs(client.sin_port);
                // //将二进制网络字节序的 IP 地址转换为可读的字符串格式
                // char ip[64];
                // const char* clientip = ::inet_ntop(AF_INET, &client.sin_addr , ip , sizeof(ip));
                InetAddr netclient(client);

                inbuffer[n] = 0;

                std::string clientinfo =netclient.IP()  + ":" + std::to_string(netclient.Port()) + " # " + inbuffer;
                LOG(LogLevel::DEBUG) << clientinfo;

                std::string echo_string = "echo# ";
                echo_string += inbuffer;

                ssize_t num_bytes =::sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, CONV(&client), len);
                if(num_bytes < 0)
                {
                    LOG(LogLevel::FATAL) << "sendto: " << strerror(errno);
                    Die(SERVER_SEND_ERR);
                }
                std::cout<<"我已发出"<<std::endl;

            }

        }
        _isrunning=false;

    }

    ~UdpServer()
    {
        if(_sockfd > gsockfd)
            ::close(_sockfd);
    }

private:
    int _sockfd;
    // uint16_t _port;
    InetAddr _netaddr;
    bool _isrunning;
};


// class UdpServer
// {
// public:
//     UdpServer(uint16_t port = gdefaultport)
//         : _port(port),
//           _sockfd(gsockfd),
//           _isrunning(false)
//     {
//     }

//     void InitServer()
//     {
//         //1.创建socket文件
//         _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0); //没有Int  这里如果定义了一个变量  _sockfd的值就是没有变化的
//         if (_sockfd < 0)                            //加 int 会变成局部变量，导致成员变量未被修改。
//         {
//             LOG(LogLevel::FATAL) << "socket: " << strerror(errno);
//             Die(SOCKET_ERR);
//         }
//         LOG(LogLevel::INFO) << "socket success, sockfd is : " << _sockfd;

//         //2.填充网络信息并bind
//         struct sockaddr_in local;
//         bzero(&local, sizeof(local));//先置零
//         local.sin_family = AF_INET;  
//         local.sin_port = ::htons(_port); // 要被发送给对方的，即要发到网络中！
//         // local.sin_addr.s_addr = ::inet_addr(_ip.c_str()); // 服务器ip不用绑定 1. string ip->4bytes 2. network order //TODO
//         local.sin_addr.s_addr = INADDR_ANY;
        
//         //bind
//         int n = ::bind(_sockfd , CONV(&local) , sizeof(local));
//         if (n < 0)
//         {
//             LOG(LogLevel::FATAL) << "bind: " << strerror(errno);
//             Die(BIND_ERR);
//         }
//         LOG(LogLevel::INFO) << "bind success";
        
//     }

//     void Start()
//     {
//         _isrunning=true;
//         //服务器启动一直运行
//         while(true)
//         {
//             //缓冲区和输出型参数
//             char inbuffer[1024]; // string
//             struct sockaddr_in client;
//             socklen_t len = sizeof(client); 

//             //服务器收信息
//             ssize_t n = ::recvfrom(_sockfd ,inbuffer ,sizeof(inbuffer)-1 ,0 ,CONV(&client) , &len);
//             if (n > 0)
//             {
//                 std::cout<<"我已收到"<<std::endl;
//                 // 1. 消息内容 && 2. 谁发给我的
//                 //16位网络数据 → 主机字节序(大端/小端)
//                 uint16_t clientport = ::ntohs(client.sin_port);
//                 //将二进制网络字节序的 IP 地址转换为可读的字符串格式
//                 char ip[64];
//                 const char* clientip = ::inet_ntop(AF_INET, &client.sin_addr , ip , sizeof(ip));
//                 inbuffer[n] = 0;

//                 std::string clientinfo = std::to_string(clientport) + ":" + clientip + " # " + inbuffer;
//                 LOG(LogLevel::DEBUG) << clientinfo;

//                 std::string echo_string = "echo# ";
//                 echo_string += inbuffer;

//                 ssize_t num_bytes =::sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, CONV(&client), len);
//                 if(num_bytes < 0)
//                 {
//                     LOG(LogLevel::FATAL) << "sendto: " << strerror(errno);
//                     Die(SERVER_SEND_ERR);
//                 }
//                 std::cout<<"我已发出"<<std::endl;

//             }

//         }
//         _isrunning=false;

//     }

//     ~UdpServer()
//     {
//         if(_sockfd > gsockfd)
//             ::close(_sockfd);
//     }

// private:
//     int _sockfd;
//     uint16_t _port;
//     bool _isrunning;
// };
